/*
 * Copyright (c) 2014. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

package com.dc.gameserver.extComponents.NettyEngine4;


import com.dc.gameserver.baseConfig.Config;
import com.dc.gameserver.extComponents.Kit.ThreadUtils.PriorityThreadFactory;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.util.concurrent.DefaultEventExecutorGroup;
import io.netty.util.concurrent.EventExecutorGroup;

/**
 * @author : 陈磊 <br/>
 *         Date: 13-3-11<br/>
 *         Time: 上午11:32<br/>
 *         connectMethod:13638363871@163.com<br/>
 *         ServerChannelInitializer which's a special handler that is purposed to help a user configure a new Channel
 *
 *      注册连接（NioServerSocketChannel   accepts incoming TCP/IP connections）上来的    channel
 *      SocketChannel  ---- A TCP/IP socket Channel  equel  to
 *       help a user configure a new Channel.
 *       this implementation must be safe to be re-used.
 *
 *
 *       线程池（接收I/O操作线程数据）处理业务逻辑数据两种方案：
 *
 *                     1、线程池直接处理数据；
 *                     2、单线程分发--->>>线程池处理；
 *
 */
public class ServerChannelInitializer extends ChannelInitializer<SocketChannel> {

    /**
     * A {@link io.netty.channel.ChannelHandler} that logs all events using a logging framework.
     * By default, all events are logged at <tt>DEBUG</tt> level.
     */
//    private static final LoggingHandler LOGGING_HANDLER=new LoggingHandler(LogLevel.DEBUG);
    /**
     * I/O线程将递交给此线程池处理数据   线程池大小为cpu核心数  ,逻辑处理线程和I/O线程分开
     * 对应一个任务是一个msg，当任务被逻辑线程处理不过来的时候将会被排队
     * 执行非I/O逻辑操作
     */
    private static final EventExecutorGroup LOGIC_EVENT_EXECUTORS=new
             DefaultEventExecutorGroup(Runtime.getRuntime().availableProcessors(),new PriorityThreadFactory("#+逻辑处理线程+#", Thread.NORM_PRIORITY ));

    public ServerChannelInitializer(){}

    /**
     * This method will be called once the {@link io.netty.channel.Channel} was registered. After the method returns this instance
     * will be removed from the {@link io.netty.channel.ChannelPipeline} of the {@link io.netty.channel.Channel}.
     *
     * @param ch the {@link io.netty.channel.Channel} which was registered.
     * @throws Exception is thrown if an error accours. In that case the {@link io.netty.channel.Channel} will be closed.
     * this channel was registered
     * 初始化channel            pipeline链表
     * 如果用于生产上，如果没有流量统计需求，则关闭流量统计功能；
     * netty4日志信息输出；流量统计 ：全局流量，单个流量统计
     * 当发布项目之后，根据实际情况是否开启流量监控功能
     *
        pipeline.addLast("logging",LOGGING_HANDLER);
        pipeline.addLast("globalTrafficShapingHandler",ServerUtil.globalTrafficShapingHandler);
        pipeline.addLast("trafficShapingHandler",ServerUtil.getChannelTrafficShapingHandler());
     */
    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();

//        /**debug logger*/
//        if (LOGGER.isDebugEnabled())pipeline.addLast("logging",LOGGING_HANDLER);

        /**解码器 inbound,默认网络字节序为大端*/
        pipeline.addLast("decoder", new ServerDecoder(Config.DEFAULT_VALUE.SERVER_VALUE.maxFrameLength
                , Config.DEFAULT_VALUE.SERVER_VALUE.lengthFieldOffset, Config.DEFAULT_VALUE.SERVER_VALUE.lengthFieldLength
                , Config.DEFAULT_VALUE.SERVER_VALUE.lengthAdjustment, Config.DEFAULT_VALUE.SERVER_VALUE.initialBytesToStrip));

        /**检查链接超时处理 inbound  心跳处理*/
        pipeline.addLast("idleStateHandler",
                new IdleStateHandler(Config.DEFAULT_VALUE.SERVER_VALUE.readTimeOut, Config.DEFAULT_VALUE.SERVER_VALUE.writeTimeOut, 0));

        /**逻辑处理 将channel交给相应的线程池处理相应的数据  I/O线程池---->>>>逻辑处理线程池*/
        pipeline.addLast(LOGIC_EVENT_EXECUTORS,"handler",new ServerHandler());

        /**编码器 outbound**/
        pipeline.addLast("encoder",new ServerEncoder());
    }
}
